GM = GM or gmod.GetGamemode() //For manual reloading

GM.buildings = {}

function GM:ParseBuildings()
	//for k,v in pairs(file.Find("ws/buildings/*.txt", "DATA")) do
	for k,v in pairs(file.Find("wintersurvival/content/data/ws/buildings/*.txt", LUA_PATH)) do
		local v = v:sub(1,#v-4) // Remove .txt
		
		// Note that we must re-append .txt
		//local str = file.Read("ws/buildings/".. v ..".txt")
		local str = file.Read("gamemodes/wintersurvival/content/data/ws/buildings/".. v .. ".txt", true)
		self:ParseBuilding(v,str)
	end
end

function GM:ParseBuilding(class,str)
	local lines = string.Explode("\n",str)
	self.buildings[class] = {}
	self.buildings[class].ents = {}
	
	for i = 1,#lines do
		local l = lines[i]
		local values = string.Explode(" ",lines[i])
		self.buildings[class].ents[i] = {}
		self.buildings[class].ents[i].ent = values[1]
		self.buildings[class].ents[i].vec = Vector(values[2],values[3],values[4])
		self.buildings[class].ents[i].ang = Angle(values[5],values[6],values[7])
		self.buildings[class].ents[i].mod = values[8]
	end
end

function GM.BuildAng(pl,cmd,args)
	local self = gmod.GetGamemode()
	local uid = pl:UniqueID()
	if tonumber(args[1]) then
		self.pldat[uid].rotation = Angle(0,math.Round(math.NormalizeAngle(tonumber(args[1]))),0)
	end
end

if SERVER then
	concommand.Add("wsBuildAng",GM.BuildAng)
end

function GM:GhostBuilding(pl,title)
	if CLIENT or not title then
		return
	end
	umsg.Start("wsbuildghost",pl)
		umsg.String(title)
	umsg.End()
end

GM.buildingdata = {}
function GM:BuildIt(pl,bclass)
	if CLIENT then
		return
	end
	
	local self = gmod.GetGamemode()
	if self.pldat[pl:UniqueID()].inventory[bclass] then
		local border = self.buildings[bclass].ents
		local tr = util.TraceLine{
			start = pl:GetShootPos(),
			endpos = pl:GetShootPos() + pl:GetAimVector()*250,
			filter = pl,
		}
		local trvalid,iblock = self:TraceValidBuild(tr,pl)
		if trvalid then
			wsUID = wsUID + 1
			self.buildingdata[wsUID] = {
				wsUID = wsUID,
				ents = {},
				class = bclass,
			}
			local tab = self.buildingdata[wsUID]
			if !self.pldat[pl:UniqueID()].rotation then
				yang = Angle(0,0,0)
			else
				yang = self.pldat[pl:UniqueID()].rotation*1
			end
			for i=1,#self.buildings[bclass].ents do
				local ent = ents.Create(border[i].ent)
				if ent:IsValid() then
					local off = border[i].vec*1
					off:Rotate(yang)
					ent:SetPos(tr.HitPos + off)
					/*
					local fishang = border[i].ang
					
					fishang:RotateAroundAxis(Vector(1,0,0),yang.p)
					fishang:RotateAroundAxis(Vector(0,0,1),yang.y)
					fishang:RotateAroundAxis(Vector(0,1,0),yang.r)
					
					ent:SetAngles(border[i].ang)
					*/
					ent:SetAngles(border[i].ang+yang)
					if border[i].mod then
						ent:SetModel(border[i].mod)
					end
					ent:GetTable().wsUID = wsUID
					ent:GetTable().class = bclass
					ent:GetTable().Owner = pl
					if iblock then
						ent:SetParent(iblock)
					end
					ent:Spawn()
					
					table.insert(tab.ents,ent)
				end
			end
			
			local item = self.items[bclass]
			if item.onBuildingInitialize then
				local b,err = pcall(item.onBuildingInitialize,item,pl,tab)
				if not b then
					error("\n"..err)
				end
			end
		end
		return trvalid
	end
	return false
end

//Helpers

function GM:BuildingUpdate(id,pl)
	local tab
	if type(id) == "number" then
		tab = self.buildingdata[id]
	elseif type(id) == "table" then
		tab = id
		id = tab.wsUID
	else
		error("number or table expected. got "..type(id))
		return
	end
	
	local inv = tab.inventory
	umsg.Start("wsBarrel",pl)
		umsg.Long(tab.wsUID)
		umsg.String(tab.class)
		umsg.Entity(tab.ents[1])
		umsg.Short(table.Count(inv))
		for k,v in pairs(inv) do
			umsg.String(k)
			umsg.Short(v.quantity)
		end
	umsg.End()
end

function GM:BuildingHas(id,class,qty)
	local qty = qty or 1
	local tab
	if type(id) == "number" then
		tab = self.buildingdata[id]
	elseif type(id) == "table" then
		tab = id
		id = tab.wsUID
	else
		error("number or table expected. got "..type(id))
		return
	end
	
	local item = self.items[class]
	if not item then
		return
	end
	
	local inv = tab.inventory
	local itemtab = inv[class]
	if not itemtab then
		return false
	end
	
	return itemtab.quantity >= qty
end

function GM:BuildingGive(id,class,qty)
	local tab
	if type(id) == "number" then
		tab = self.buildingdata[id]
	elseif type(id) == "table" then
		tab = id
		id = tab.wsUID
	else
		error("number or table expected. got "..type(id))
		return
	end
	
	local item = self.items[class]
	if not item then
		return
	end
	
	local inv = tab.inventory
	local itemtab = inv[class]
	if not itemtab then
		itemtab = {}
		inv[class] = itemtab
		itemtab.quantity = 0
		itemtab.item = item
	end
	
	itemtab.quantity = itemtab.quantity+qty
	
	if itemtab.quantity <= 0 then
		inv[class] = nil
	end
	
	local rp = RecipientFilter()
	rp:AddAllPlayers()
	umsg.Start("wsBarUpd",rp)
		umsg.Long(id)
	umsg.End()
end

if SERVER then
	concommand.Add("wsBarReq",function(pl,cmd,args)
		local self = gmod.GetGamemode()
		
		local id = tonumber(args[1])
		if not id then
			return
		end
		
		local tab = self.buildingdata[id]
		if not tab then
			return
		end
		
		local oent = tab.ents[1]
		if not (oent and (oent:GetPos() - pl:GetPos()):Length() < 256) then
			umsg.Start("wsBarOOR",pl) //Notify client that they are Out Of Range (For when they call this function manually,because normally the below code will never be executed)
				umsg.Long(id)
			umsg.End()
			return
		end
		
		self:BuildingUpdate(tab,pl)
	end)
end


























